15. 【选修】练习:迭代器和生成器
练习:实现 my_enumerate
请自己写一个效果和内置函数 enumerate
一样的生成器函数。
如下所示地调用该函数:
lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"]
for i, lesson in my_enumerate(lessons, 1):
print("Lesson {}: {}".format(i, lesson))
应该会输出:
Lesson 1: Why Python Programming
Lesson 2: Data Types and Operators
Lesson 3: Control Flow
Lesson 4: Functions
Lesson 5: Scripting
Start Quiz:
lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"]
def my_enumerate(iterable, start=0):
# Implement your generator function here
for i, lesson in my_enumerate(lessons, 1):
print("Lesson {}: {}".format(i, lesson))
为何要使用生成器?
你可能会疑问,为何要使用生成器,而不使用列表。下面这段摘自 stack overflow 页面 的内容回答了这个问题:
生成器是构建迭代器的 “懒惰” 方式。当内存不够存储完整实现的列表时,或者计算每个列表元素的代价很高,你希望尽量推迟计算时,就可以使用生成器。但是这些元素只能遍历一次。
另一种详细的解释如下(详细说明参见 该 stack overflow 页面。)
由于使用生成器是一次处理一个数据,在内存和存储的需求上会比使用 list 方式直接全部生成再存储节省很多资源。
由此区别,在处理大量数据时,经常使用生成器初步处理数据后,再进行长期存储,而不是使用 list。因为无论使用生成器还是 list,都是使用过就要丢弃的临时数据。既然功能和结果一样,那就不如用生成器。
但是生成器也有自己的局限,它产生的数据不能回溯,不像 list 可以任意选择。
练习:Chunker
如果可迭代对象太大,无法完整地存储在内存中(例如处理大型文件时),每次能够使用一部分很有用。
实现一个生成器函数 chunker
,接受一个可迭代对象并每次生成指定大小的部分数据。
如下所示地调用该函数:
for chunk in chunker(range(25), 4):
print(list(chunk))
应该会输出:
[0, 1, 2, 3]
[4, 5, 6, 7]
[8, 9, 10, 11]
[12, 13, 14, 15]
[16, 17, 18, 19]
[20, 21, 22, 23]
[24]
Start Quiz:
def chunker(iterable, size):
# Implement function here
for chunk in chunker(range(25), 4):
print(list(chunk))